package com.jacky;
import com.mysql.cj.jdbc.JdbcConnection;
import com.mysql.cj.jdbc.MysqlXAConnection;
import com.mysql.cj.jdbc.MysqlXid;
import javax.sql.XAConnection;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class XaDemo {

    public static void main(String[] args) throws Exception {
        //打印xa语句
        boolean logXaCommands = true;
        // 获得资源管理器操作接口实例 RM1
        Connection conn01 = DriverManager.getConnection("jdbc:mysql://10.22.0.84:31877/xa1-demo", "root", "root");
        XAConnection xaConn01 = new MysqlXAConnection((JdbcConnection) conn01, logXaCommands);
        XAResource resourceManager1 = xaConn01.getXAResource();

        // 获得资源管理器操作接口实例 RM2
        Connection conn02 = DriverManager.getConnection("jdbc:mysql://10.22.0.84:31877/xa2-demo", "root", "root");
        XAConnection xaConn02 = new MysqlXAConnection((JdbcConnection) conn02, logXaCommands);
        XAResource resourceManager2 = xaConn02.getXAResource();

        // 请求TM执行一个分布式事务，TM生成全局事务id
        byte[] globalXid = "0000000".getBytes();
        int formatId = 1;
        Xid branchXid1 = null;
        Xid branchXid2 = null;
        try {
            // ==============分别执行RM1和RM2上的事务分支====================
            // TM生成rm1上的事务分支id
            try {
                byte[] branch01 = "0000001".getBytes();
                branchXid1 = new MysqlXid(globalXid, branch01, formatId);
                String sql01 = String.format("UPDATE t_account SET money=money-%s WHERE account_name='%s'", 100,"songyao");
                // 执行rm1上的事务分支
                resourceManager1.start(branchXid1, XAResource.TMNOFLAGS);
                PreparedStatement ps1 = conn01.prepareStatement(sql01);
                ps1.execute();
                resourceManager1.end(branchXid1, XAResource.TMSUCCESS);
            } catch (Exception e) {
                resourceManager1.end(branchXid2, XAResource.TMFAIL);
                throw new Exception(e);
            }
            // TM生成rm2上的事务分支id
            try {
                byte[] branch02 = "0000002".getBytes();
                branchXid2 = new MysqlXid(globalXid, branch02, formatId);
                String sql2 = String.format("UPDATE t_account SET money=money+%s WHERE account_name='%s'", 100,"limei");
                //会报错的sql
                //String sql2 = String.format("INSERT INTO `xa2-demo`.`user_info` (`id`,`user_name`) VALUES ('%s','%s')", "1", "limei");
                // 执行rm2上的事务分支
                resourceManager2.start(branchXid2, XAResource.TMNOFLAGS);
                PreparedStatement ps2 = conn02.prepareStatement(sql2);
                ps2.execute();
                resourceManager2.end(branchXid2, XAResource.TMSUCCESS);
            } catch (Exception e) {
                resourceManager2.end(branchXid2, XAResource.TMFAIL);
                throw new Exception(e);
            }
            // 表示第一阶段准备好了
            int rm1_prepare = resourceManager1.prepare(branchXid1);
            int rm2_prepare = resourceManager2.prepare(branchXid2);
           // ===================两阶段提交================================
            // 表示是二阶段提交
            boolean onePhase = false;
            if (rm1_prepare == XAResource.XA_OK && rm2_prepare == XAResource.XA_OK) {
                //所有事务分支都prepare成功，提交所有事务分支
                resourceManager1.commit(branchXid1, onePhase);
                resourceManager2.commit(branchXid2, onePhase);
            } else {
                //如果有事务分支没有成功，则回滚
                resourceManager1.rollback(branchXid1);
                resourceManager2.rollback(branchXid2);
            }
        } catch (Exception e) {
            // 如果出现异常，也要进行回滚
            resourceManager1.rollback(branchXid1);
            resourceManager2.rollback(branchXid2);
            e.printStackTrace();
        }

    }

}